/********************************************************************************
* Project       : No Latency RTSP streaming Project
* Desc          : Xwindow module
* Author        : Seo, SeokWon 
* e-mail        : kueony@gmail.com
* Licence       : See the Copyright
*********************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include "lib_log.h"
#include "vll_x11.h"

#define MSET(x) memset (&(x), 0, sizeof(x))

/*****************************************************************************/
/* Functions */
/*****************************************************************************/
static int create_win_n_image(st_x11_data* a_x11, int a_width, int a_height);

int create_xwindow(st_x11_data* a_x11, int a_win_width, int a_win_height)
{
	a_x11->win_width	= a_win_width;
	a_x11->win_height	= a_win_height;
	
	if(create_win_n_image(a_x11, a_win_width, a_win_height) < 0){
		LogMsg(LIB_LOG_TYPE_ERROR, "(%s, %d) %s", __FILE__, __LINE__, "fail_create_win");
		goto ERR_HANDLER;
	}

	return 0;
	
ERR_HANDLER:
	destroy_xwindow(a_x11);
	return -1;	
}

void destroy_xwindow(st_x11_data* a_x11)
{
	if(a_x11->xImage == NULL) return;
	
	if (a_x11->xImage->data != NULL) {
		free(a_x11->xImage->data);
		a_x11->xImage->data = NULL;		
	}
	
	XDestroyImage(a_x11->xImage);
	a_x11->xImage = NULL;
	
	if (a_x11->display != NULL){
		XFreeGC(a_x11->display, a_x11->gc);
		a_x11->display = NULL;
	}
	
	return;
}

void draw(st_x11_data* a_x11)
{
	XPutImage(a_x11->display, a_x11->window, a_x11->gc, a_x11->xImage, 0, 0, 0, 0, a_x11->win_width, a_x11->win_height);
//	XFlush(a_x11->display);	
	
	return;
}


static int create_win_n_image(st_x11_data* a_x11, int a_width, int a_height)
{
	XGCValues          gcValues;
	ulong              gcValuesMask;
	XWindowAttributes  windowAttributes;

	if ((a_x11->display = XOpenDisplay(NULL)) == NULL){
		LogMsg(LIB_LOG_TYPE_ERROR, "(%s, %d) %s", __FILE__, __LINE__, "XOpenDisplay");
		return -1;
	}
	
	a_x11->screen_num	= DefaultScreen(a_x11->display);
	a_x11->screen		= XScreenOfDisplay(a_x11->display, a_x11->screen_num);

	a_x11->window		= XCreateSimpleWindow(a_x11->display, RootWindowOfScreen(a_x11->screen), 0, 0, a_width, a_height, 0, 		BlackPixelOfScreen(a_x11->screen), BlackPixelOfScreen(a_x11->screen));

	a_x11->xImage		= NULL;

	gcValues.function	= GXcopy;
	gcValuesMask		= GCFunction;
	a_x11->gc			= XCreateGC(a_x11->display, a_x11->window, gcValuesMask, &gcValues);

	XGetWindowAttributes(a_x11->display, a_x11->window, &windowAttributes);

	a_x11->visual		= windowAttributes.visual;
	a_x11->depth		= windowAttributes.depth;
	
	if(a_x11->depth != 24){
		LogMsg(LIB_LOG_TYPE_ERROR, "(%s, %d) %s", __FILE__, __LINE__, "cannot_support_win_depth");
		return -1;
	}

	a_x11->xImage = XCreateImage(a_x11->display, a_x11->visual, a_x11->depth, ZPixmap, 0, NULL, a_width, a_height, 16, 0);
	
	if(a_x11->xImage == NULL){
		LogMsg(LIB_LOG_TYPE_ERROR, "(%s, %d) %s", __FILE__, __LINE__, "XCreateImage");
		return -1;
	}
		
	// rgb8888: 4bytes per pixels = width * height * 4
	a_x11->data_size	= a_x11->xImage->bytes_per_line * a_x11->xImage->height;
	a_x11->xImage->data = (char *) malloc(a_x11->data_size);

	if(a_x11->xImage->data == NULL){
		LogMsg(LIB_LOG_TYPE_ERROR, "(%s, %d) %s", __FILE__, __LINE__, "malloc");
		return -1;
	}

	XMapRaised(a_x11->display, a_x11->window);
	XFlush(a_x11->display);

	return 0;
}

